- Published on
폼 레이아웃을 도와주는 다른 방법들
- Authors
- Name
- Hyo814
폼 레이아웃을 도와주는 다른 방법들(Form.py)
공식 문서 :
https://docs.djangoproject.com/en/5.2/topics/forms/modelforms/
https://django-crispy-forms.readthedocs.io/en/latest/
https://django-tailwind.readthedocs.io/en/latest/
https://django-formify.readthedocs.io/en/latest/
기타사항.
https://github.com/elo80ka/django-dynamic-formset
https://github.com/jazzband/django-widget-tweaks
https://github.com/elo80ka/django-dynamic-formset
https://django-bootstrap5.readthedocs.io/en/latest/
라이브러리 | 구조 제어 | 스타일 프레임워크 연동 | 주요 특징 |
---|---|---|---|
django-crispy-forms | ✅ | Bootstrap / Tailwind | Python 코드로 레이아웃 제어 |
django-formify | ✅ | Tailwind 전용 | 컴포넌트 기반 구조 설계 |
django-widget-tweaks | ❌ | 자유 (템플릿에서 조작) | 템플릿에서 필드 속성 조작 |
django-bootstrap5 | ❌ | Bootstrap 전용 | 자동 렌더링, 커스터마이징은 제한 |
django-dynamic-formset | ❌ | 자유 (JS 조작 중심) | 클라이언트에서 Form 행 추가/삭제 |
widget
) 커스터마이징
1. 위젯(forms.CharField(
widget=forms.TextInput(attrs={
"class": "input input-bordered",
"placeholder": "이름을 입력하세요",
"autocomplete": "off",
"maxlength": "30",
"required": "required"
})
)
자주 사용하는 HTML 속성 (Tailwind 포함)
class
,placeholder
,type
,autocomplete
,maxlength
,required
,readonly
,disabled
,id
,data-*
<textarea>
전용:rows
,cols
- 입력 제한:
min
,max
,minlength
,pattern
,step
forms.Field
공통 속성 확장
2. 속성 | 설명 |
---|---|
label | 레이블 텍스트 |
help_text | 입력 안내 문구 |
error_messages | 유효성 검사 실패 시 메시지 |
initial | 기본값 |
required | 필수 여부 (기본값: True) |
disabled | 비활성화 설정 |
widget | 위젯 지정 |
validators | 커스텀 유효성 검사 함수 리스트 |
localize | 로컬라이징 포맷 사용 여부 |
input_formats | 날짜/시간 허용 포맷 리스트 |
ModelForm.Meta
속성 정리
3. 속성 | 설명 |
---|---|
model | 연결할 모델 클래스 |
fields | 포함할 필드 목록 |
exclude | 제외할 필드 목록 |
widgets | 필드별 위젯 커스터마이징 |
labels | 필드 레이블 지정 |
help_texts | 필드별 안내 문구 |
error_messages | 필드별 에러 메시지 |
localized_fields | 포맷 로컬라이징할 필드 |
field_classes | 필드 클래스 직접 지정 |
crispy_forms
+ ModelForm
Layout 구성
4. self.helper.layout = Layout(
Row(
Column('username', css_class='w-full'),
Column('email', css_class='w-full'),
),
Row(
Column('birth_date', css_class='w-full'),
Column('phone', css_class='w-full'),
),
Submit('submit', '저장하기', css_class='btn btn-primary w-full')
)
그룹화 및 커스텀 HTML 삽입 예시
self.helper.layout = Layout(
HTML("<h3 class='text-lg font-bold mb-4'>기본 정보</h3>"),
Row(Column('username'), Column('email')),
HTML("<h3 class='text-lg font-bold mt-6 mb-4'>기타 정보</h3>"),
Row(Column('birth_date'), Column('phone')),
Submit('submit', '수정하기')
)
5. 조건부 렌더링 및 필드 처리
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
if not user.is_staff:
self.fields.pop('phone')
self.fields['email'].widget = forms.HiddenInput()
self.fields['username'].disabled = True
Form
vs ModelForm
비교 요약
6. 항목 | forms.Form | forms.ModelForm |
---|---|---|
모델 연결 | 없음 | 있음 (Meta.model ) |
필드 정의 | 수동 정의 | 모델 기반 자동 생성 |
Meta 클래스 | 선택 | 필수 |
저장 방식 | .cleaned_data 직접 처리 | .save() 자동 저장 |
활용 예 | 검색, 문의, 확인 입력 등 | 등록, 수정, 저장 필요 폼 |
forms.Form
7. 예시 코드: class ContactForm(forms.Form):
name = forms.CharField(max_length=30)
message = forms.CharField(widget=forms.Textarea)
forms.ModelForm
8. 예시 코드: class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
widgets = {
'content': forms.Textarea(attrs={
"class": "w-full p-3 border rounded-md",
"placeholder": "내용을 입력하세요"
})
}